/*
 * TestTokenizers.java
 * Created on Nov 26, 2009, 2:42:23 PM
 */
package com.googlecode.blaisemath.parser;

/*
 * #%L
 * BlaiseParser
 * --
 * Copyright (C) 2009 - 2015 Elisha Peterson
 * --
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import com.googlecode.blaisemath.parser.SemanticTreeEvaluationException;
import com.googlecode.blaisemath.parser.ParseException;
import com.googlecode.blaisemath.parser.TokenType;
import com.googlecode.blaisemath.parser.SemanticNode;
import com.googlecode.blaisemath.parser.Grammar;
import com.googlecode.blaisemath.parser.TokenNode;
import com.googlecode.blaisemath.parser.TokenParser;
import java.awt.Color;
import java.lang.reflect.Array;
import java.util.ArrayList;
import javax.swing.DefaultComboBoxModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultTreeModel;
import com.googlecode.blaisemath.parser.TokenParser.Tokenizer;

/**
 *
 * @author elisha
 */
public class ParserTestApp extends javax.swing.JFrame {

    /** Creates new form TestTokenizers */
    public ParserTestApp() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jToolBar1 = new javax.swing.JToolBar();
        jLabel1 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jComboBox1 = new javax.swing.JComboBox();
        jButton1 = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        value = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        vars = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        tokenTable = new javax.swing.JTable();
        jScrollPane1 = new javax.swing.JScrollPane();
        tokenTree = new javax.swing.JTree();
        jScrollPane3 = new javax.swing.JScrollPane();
        semanticTree = new javax.swing.JTree();
        status = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jToolBar1.setRollover(true);

        jLabel1.setText("String:");
        jToolBar1.add(jLabel1);

        jTextField1.setText("jTextField1");
        jTextField1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                jTextField1KeyReleased(evt);
            }
        });
        jToolBar1.add(jTextField1);

        jComboBox1.setModel(new DefaultComboBoxModel(ParserType.values()));
        jToolBar1.add(jComboBox1);

        jButton1.setText("GO!!");
        jButton1.setFocusable(false);
        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jToolBar1.add(jButton1);

        jLabel2.setText("   value = ");
        jToolBar1.add(jLabel2);

        value.setFont(new java.awt.Font("Times New Roman", 0, 18)); // NOI18N
        value.setText("N/A");
        jToolBar1.add(value);

        jLabel3.setText("  variables = ");
        jToolBar1.add(jLabel3);

        vars.setFont(new java.awt.Font("Times New Roman", 0, 18)); // NOI18N
        vars.setText("[]");
        jToolBar1.add(vars);

        getContentPane().add(jToolBar1, java.awt.BorderLayout.NORTH);

        jPanel1.setLayout(new java.awt.GridLayout(1, 0));

        tokenTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jScrollPane2.setViewportView(tokenTable);

        jPanel1.add(jScrollPane2);

        tokenTree.setPreferredSize(new java.awt.Dimension(300, 64));
        jScrollPane1.setViewportView(tokenTree);

        jPanel1.add(jScrollPane1);

        jScrollPane3.setViewportView(semanticTree);

        jPanel1.add(jScrollPane3);

        getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);

        status.setText("OK.");
        getContentPane().add(status, java.awt.BorderLayout.PAGE_END);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        String expression = jTextField1.getText();
        Grammar g = ((ParserType)jComboBox1.getSelectedItem()).g;

        // create token table
        try {
            ArrayList<String> tokens = new ArrayList<String>();
            ArrayList<TokenType> types = new ArrayList<TokenType>();
            if (jComboBox1.getSelectedItem()==ParserType.REAL) {
                new Tokenizer(g).tokenize(expression, tokens, types);
                TokenParser.convertFunctionTypes(tokens, types, g);
            } else if (jComboBox1.getSelectedItem()==ParserType.BOOLEAN) {
                new Tokenizer(g).tokenize(expression, tokens, types);
                TokenParser.convertFunctionTypes(tokens, types, g);
            }
            Object[][] data = new Object[tokens.size()][2];
            String[] colNames = {"Token", "Type"};
            for (int i = 0; i < data.length; i++) {
                data[i][0] = tokens.get(i);
                data[i][1] = types.get(i);
            }
            tokenTable.setModel(new DefaultTableModel(data, colNames));
        } catch (ParseException ex) {
        }

        // create token tree
        try {
            TokenNode topNode = new TokenParser(g).tokenizeTree(expression);
            tokenTree.setModel(new DefaultTreeModel(topNode));
            jTextField1.setForeground(Color.BLACK);
            status.setText("OK");
        } catch (ParseException ex) {
            Color col = null;
            switch (ex.code) {
                case PARENTHETICAL_ERROR:
                    col = Color.ORANGE;
                    break;
                case UNRECOGNIZED_SYMBOL:
                    col = Color.GREEN;
                    break;
                case INVALID_OPERATOR_POSITION:
                    col = Color.RED;
                    break;
                case ENDED_EARLY:
                    col = Color.GRAY;
                    break;
                case UNKNOWN_ERROR:
                    col = Color.MAGENTA;
                    break;
            }
            jTextField1.setForeground(col);
            status.setText(ex.toString());
            return;
        }

        // create semantic tree and show values
        SemanticNode sNode = null;
        try {
            sNode = new TokenParser(g).parseTree(expression);
            semanticTree.setModel(new DefaultTreeModel(sNode));
            
            // compute value
            try {
                Object val = sNode.getValue();
                if (val.getClass().isArray()) {
                    if (Array.getLength(val)==0) {
                        value.setText("[]");
                    } else {
                        String s = "[" + Array.get(val, 0).toString();
                        for (int i = 1; i < Array.getLength(val); i++) {
                            s += ", " + Array.get(val, i).toString();
                        }
                        s += "]";
                        value.setText(s);
                    }
                } else
                    value.setText(val.toString());
                value.setForeground(Color.BLUE);
            } catch (SemanticTreeEvaluationException ex) {
                status.setText("Error evaluating semantic tree");
                value.setText("N/A");
                value.setForeground(Color.RED);
            }
            
            // compute variables
            vars.setText(sNode.getVariables().toString());
            value.setForeground(Color.BLUE);
        } catch (ParseException ex) {
            status.setText("Error building semantic tree (parse).");
            System.out.println(ex.toString());
            value.setText("N/A");
            value.setForeground(Color.RED);
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jTextField1KeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTextField1KeyReleased
        jButton1ActionPerformed(null);
    }//GEN-LAST:event_jTextField1KeyReleased

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ParserTestApp().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JTree semanticTree;
    private javax.swing.JLabel status;
    private javax.swing.JTable tokenTable;
    private javax.swing.JTree tokenTree;
    private javax.swing.JLabel value;
    private javax.swing.JLabel vars;
    // End of variables declaration//GEN-END:variables
}
